位运算(+,-,*,/)

Tips:本文所用例子均为整数,并未考虑浮点数等情况

1. 位运算符

Tips:A、B两个变量提供给下述表格样例演示

A = (0b0011)

B = (0b1101)

操作符 名称 作用 样例
| 按位或 按位或运算符“|”是双目运算符,其主要的作用就是使两个数对应的二进制位进行相或,只要对应的两个二进制位有一个为1时,则对应的结果位为1 (A | B) == (0b1111)
& 按位与 按位与运算符“&”是双目运算符,其主要的作用就是使两个数对应的二进制位进行相与,只有当对应的两个二进制位均位1时,对应的结果为才为1 (A & B) == (0b0001)
^ 按位异或 按位异或运算符”^“是双目运算符,其主要的作用就是是两个数对应的二进制位进行相异或,当对应的两个二进制位均为1或均为0时,则结果为0,否则结果为1 (A ^ B) == (0b1110)
~ 取反 取反运算符”~“为单目运算符,具有右结合性,其主要的作用就是对参与运算的数对应的二进制位按位取反,即每一位的1变为0,0变为1 (A) == (0b1100) (B) == (0b0010)
<< 左移 左移运算符”<<“为双目运算符,左移n位实际上就是乘以2的n次方,其功能就是把运算符左边的数对应的二进制位全部左移若干位,高位丢弃,低位则补0 (A << 1) == (0b0110) (B << 1) == (0b11010)
>> 右移 右移运算符”>>“为双目运算符,右移n位实际上就是除以2的n次方,其功能就是把运算符左边的数对应的二进制位全部右移若干位,低位丢弃 (A >> 1) == (0b0001) (B >> 1) == (0b0110)

2. 加法(+)

整个加法流程可以分解为两个部分,即循环求出不进位的和求出进位后的和,再对其两者进行异或操作,直至求出进位的和为0,得到结果,具体代码如下所示。

其中num1 ^ num2可求出不进位的和,(num1 & num2) << 1则可求出进位后的和。

1
2
3
4
5
6
7
8
9
10
11
12
public static int add(int num1, int num2) {
// num1 == 0b100, num2 == 0b110
while(num2 != 0) {
// 不进位的和 (0b100 ^ 0b110 == 0b010)
int add = (num1 ^ num2);
// 进位的和 (0b100 & 0b110 == 0b100) -> (0b100 << 1 == 0b1000)
num2 = ((num1 & num2) << 1);
num1 = add;
}
// num1 == 0b1010
return num1;
}

3. 减法(-)

实际上减法a - b = c可看为a + (-b) = c,所以此处可根据加法进行改造,代码如下所示。

其中需要注意的是b转换为-b则需要进行取反后+1。

1
2
3
public static int sub(int num1, int num2) {
return add(num1, add(1, ~num2));
}

4. 乘法(*)

乘法操作A * B = C中,按照B的对应的二进制数中的情况进行加操作,具体代码如下所示。

1
2
3
4
5
6
7
8
9
public static int multiplication(int num1, int num2) {
int res = 0;
while(num2 != 0) {
if((num2 & 1) == 1) res = add(res, num1);
num1 <<= 1;
num2 >>= 1;
}
return res;
}

5. 除法(/)

除法操作中,进行累减,累减次数则为结果。

1
2
3
4
5
6
7
8
9
10
11
public static int division(int num1, int num2) {
int res = 0;
boolean flag = !((num1 >= 0 && num2 >= 0) || (num1 < 0 && num2 < 0));
num1 = Math.abs(num1);
num2 = Math.abs(num2);
while (num1 >= num2) {
num1 = sub(num1, num2);
res = add(res, 1);
}
return (flag) ? -res : res;
}